﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team - cellcloudproject@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#ifndef CellException_h
#define CellException_h

#include "CellPrerequisites.h"
#include "CellHeaderPrefix.h"
#include "CellString.h"
#include <exception>

// Check for CELL assert mode

// RELEASE_EXCEPTIONS mode
#if CELL_ASSERT_MODE == CELL_ASSERT_MODE_RELEASE_EXCEPTIONS
#   ifdef _DEBUG
#       define CellAssert( a, b ) assert( (a) && (b) )

#   else
#       if CELL_COMPILER != CELL_COMPILER_BORL
#           define CellAssert( a, b ) if( !(a) ) CELL_EXCEPT( cell::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
#       else
#           define CellAssert( a, b ) if( !(a) ) CELL_EXCEPT( cell::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
#       endif

#   endif

// EXCEPTIONS mode
#elif CELL_ASSERT_MODE == CELL_ASSERT_MODE_EXCEPTIONS
#   if CELL_COMPILER != CELL_COMPILER_BORL
#       define CellAssert( a, b ) if( !(a) ) CELL_EXCEPT( cell::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
#   else
#       define CellAssert( a, b ) if( !(a) ) CELL_EXCEPT( cell::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
#   endif

// STANDARD mode
#else
#   define CellAssert( a, b ) assert( (a) && (b) )

#endif

namespace cell
{
/** \addtogroup Core
 *  @{
 */
/** \addtogroup General
 *  @{
 */

/** 异常描述类。当程序抛出异常时，提供了 Cell Cloud 内的错误信息。
@author
	Jiangwei Xu
@remarks
	一般的，Cell Cloud 不使用返回值来表示程序是否出错。
	当程序发生错误时，Cell Cloud 将抛出异常，该异常对象携带了发生错误对象的详细信息。
	因此，通过捕获异常的方式可以获知程序的错误信息。
	使用以下代码段，可以捕获到 Cell Cloud 的异常：
		try{} catch(cell::Exception& e) {}
@par
	用户程序不允许实例化该对象。
*/
class _CellExport Exception : public std::exception
{
public:
	/** 错误码定义。
	@todo
		添加更多的异常代码。
	*/
	enum ExceptionCodes {
		ERR_IO_ERROR,
		ERR_INVALID_STATE,
		ERR_INVALID_PARAMS,
		ERR_API_ERROR,
		ERR_DUPLICATE_ITEM,
		ERR_ITEM_NOT_FOUND,
		ERR_FILE_NOT_FOUND,
		ERR_INTERNAL_ERROR, 
		ERR_NOT_IMPLEMENTED
	};

	/** 默认构造函数。
	*/
	Exception(int number, const String& description, const String& source);

	/** 构造函数。
	*/
	Exception(int number, const String& description, const String& source, const char* type, const char* file, long line);

	/** 拷贝构造函数。
	*/
	Exception(const Exception& rhs);

	/// 析构函数。兼容 std::exception
	~Exception() throw() {}

	/** 赋值操作符。
	*/
	void operator = (const Exception& rhs);

	/** 返回字符串形式的错误信息的完整描述。
	@remarks
		描述内容包括错误号、抛出异常的程序和应用程序工作的平台相关信息。
	*/
	virtual const String& getFullDescription(void) const;

	/** 返回错误号。
	*/
	virtual int getNumber(void) const throw();

	/** 返回源函数。
	*/
	virtual const String &getSource() const { return source; }

	/** 返回源代码文件名。
	*/
	virtual const String &getFile() const { return file; }

	/** 返回代码行号。
	*/
	virtual long getLine() const { return line; }

	/** 返回异常的描述文本内容。
	*/
	virtual const String &getDescription(void) const { return description; }

	/// 覆盖 std::exception::what
	const char* what() const throw() { return getFullDescription().c_str(); }
        
protected:
	long line;
	int number;
	String typeName;
	String description;
	String source;
	String file;
	mutable String fullDesc;
};


/** 用于创建指定类型的异常码的模板结构体。
*/
template <int num>
struct ExceptionCodeType
{
	enum { number = num };
};

// 定义系统内置的异常。

class _CellExport UnimplementedException : public Exception 
{
public:
	UnimplementedException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "UnimplementedException", file, line) {}
};
class _CellExport FileNotFoundException : public Exception
{
public:
	FileNotFoundException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "FileNotFoundException", file, line) {}
};
class _CellExport IOException : public Exception
{
public:
	IOException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "IOException", file, line) {}
};
class _CellExport InvalidStateException : public Exception
{
public:
	InvalidStateException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "InvalidStateException", file, line) {}
};
class _CellExport InvalidParametersException : public Exception
{
public:
	InvalidParametersException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "InvalidParametersException", file, line) {}
};
class _CellExport ItemIdentityException : public Exception
{
public:
	ItemIdentityException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "ItemIdentityException", file, line) {}
};
class _CellExport InternalErrorException : public Exception
{
public:
	InternalErrorException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "InternalErrorException", file, line) {}
};
class _CellExport APIException : public Exception
{
public:
	APIException(int number, const String& description, const String& source, const char* file, long line)
		: Exception(number, description, source, "APIException", file, line) {}
};

/** 实现多个重载方法的类，通过模板实现构建对应异常代码的异常对象。
*/
class _CellPrivate ExceptionFactory
{
private:
	/// 私有构造函数，不允许构造该对象。
	ExceptionFactory() {}
public:
	static UnimplementedException create(
		ExceptionCodeType<Exception::ERR_NOT_IMPLEMENTED> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return UnimplementedException(code.number, desc, src, file, line);
	}
	static FileNotFoundException create(
		ExceptionCodeType<Exception::ERR_FILE_NOT_FOUND> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return FileNotFoundException(code.number, desc, src, file, line);
	}
	static IOException create(
		ExceptionCodeType<Exception::ERR_IO_ERROR> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return IOException(code.number, desc, src, file, line);
	}
	static InvalidStateException create(
		ExceptionCodeType<Exception::ERR_INVALID_STATE> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return InvalidStateException(code.number, desc, src, file, line);
	}
	static InvalidParametersException create(
		ExceptionCodeType<Exception::ERR_INVALID_PARAMS> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return InvalidParametersException(code.number, desc, src, file, line);
	}
	static ItemIdentityException create(
		ExceptionCodeType<Exception::ERR_ITEM_NOT_FOUND> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return ItemIdentityException(code.number, desc, src, file, line);
	}
	static ItemIdentityException create(
		ExceptionCodeType<Exception::ERR_DUPLICATE_ITEM> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return ItemIdentityException(code.number, desc, src, file, line);
	}
	static InternalErrorException create(
		ExceptionCodeType<Exception::ERR_INTERNAL_ERROR> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return InternalErrorException(code.number, desc, src, file, line);
	}
	static APIException create(
		ExceptionCodeType<Exception::ERR_API_ERROR> code, 
		const String& desc, 
		const String& src, const char* file, long line)
	{
		return APIException(code.number, desc, src, file, line);
	}
};


	/// 抛出指定异常代码的宏定义。
#ifndef CELL_EXCEPT
#define CELL_EXCEPT(num, desc, src) throw cell::ExceptionFactory::create( \
	cell::ExceptionCodeType<num>(), desc, src, __FILE__, __LINE__ );
#endif

/** @} */
/** @} */
} // end namespace cell

#include "CellHeaderSuffix.h"

#endif // CellException_h
